﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Admin.NET.Application.Entity;
using Admin.NET.Application.Inventory.InventoryService;
using Admin.NET.Application.Service.Position.Dto;
using Admin.NET.Application.Service.Warehouse;
using Aop.Api.Domain;
using Elastic.Clients.Elasticsearch.Snapshot;
using Hardware.Info;
using MathNet.Numerics.Distributions;
using MQTTnet;
using MyDemo.Application.Service.Plc;
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;
using WCS.Application.Service.Inventory.DTO;
using static SKIT.FlurlHttpClient.Wechat.Api.Models.ChannelsECWarehouseGetResponse.Types;
using static SKIT.FlurlHttpClient.Wechat.Api.Models.WxaSecVodCommitUploadRequest.Types;

namespace WCS.Application.Service.Plc;
/// <summary>
/// 
/// 调用
/// </summary>
[ApiDescriptionSettings(groups: ApplicationConst.GroupName, Order = 9)]
[AllowAnonymous]
public class AgvCommunication : IDynamicApiController
{
    //mqtt
    private readonly MqttService _mqttClientService;
    //redis
    private readonly SysCacheService _sysCacheService;
    //库位
    //private readonly WarehouseInfomationService _warehouse;
    //库存
    private readonly InventoryService _inventoryService;
    private readonly SqlSugarRepository<InventoryManagementEntity> _inventory;
    public AgvCommunication(SysCacheService sysCacheService, MqttService mqttClientService, SqlSugarRepository<InventoryManagementEntity> inventory)
    {
        _sysCacheService = sysCacheService;
        _mqttClientService = mqttClientService;
         // _inventoryService = inventoryService; 
         _inventory = inventory;
    }
    // 此方法用于获取 uint16 指定位的值
    public static bool GetBitValue(ushort number, int bitPosition)
    {

        if (bitPosition < 0 || bitPosition > 15)
        {
            throw new ArgumentException("位位置必须在 0 到 15 之间。");
        }
        return (number & (1u << bitPosition)) != 0;
    }

    // 使用示例
    /// <summary>  
    /// 正常驾驶  
    /// </summary>  
    /// <returns></returns>  
    [ApiDescriptionSettings(Name = "Normaldriving"), HttpPost]
    public async Task<bool> Normaldriving(WcsReaderWriteRgv rgvDto, string topic)
    {
        Feedback feedbackDto = new Feedback();
        WcsReaderWriteRgv mqttReaderWrite = new WcsReaderWriteRgv();

        // 判断AGV是否运行读  
        var stringAgvStatus = await _mqttClientService.RedisGet("WarehouseAGV02", nameof(feedbackDto.Wm200));
        var stringMqttRead = await _mqttClientService.RedisGet("WarehouseAGV01", nameof(mqttReaderWrite.Wm003));
        var stringfeedbackDto = await _mqttClientService.RedisGet("WarehouseAGV02");


        var bit=Convert.ToString(456, 2).PadLeft(16, '0');
        for (int i = 0; i < 5; i++)
        {
            //前面
            bool bitValue = GetBitValue(456, i);
            Console.WriteLine($"第 {i} 位的值是: {bitValue}");
        }
        
           
        
        //读取反馈状态  
        feedbackDto = JsonConvert.DeserializeObject<Feedback>(stringfeedbackDto);
        //mqttReaderWrite = JsonConvert.DeserializeObject<WcsReaderWriteRgv>(stringAgvStatus);
        if (stringAgvStatus == "0")
        {
            try
            {
                if (feedbackDto.Wm201 == 0)
                {
                    throw Oops.Oh($"未扫描到码值，请稍后再试");

                }
                //空闲逻辑  
                if (feedbackDto.Wm204 != 0)
                {
                    throw Oops.Oh($"AGV出错，请稍后再试 RGV错误编号:{feedbackDto.GetError204}");
                }
                // 校验 Wm205 的 5 位  
                if (!ValidateWm205Bits(feedbackDto.Wm205, 0, 5))
                {
                    throw Oops.Oh($"RGV顶升位置、充电开关状态位，请检查反馈值: {feedbackDto.GetLift205StatusByValue(feedbackDto.Wm205)}");
                }
                //206
                //校验给的反馈逻辑
                //
                //托盘  
                if (!ValidateWm205Bits(feedbackDto.Wm207, 1, 6))
                {
                    throw Oops.Oh($"托盘出错，请稍后再试:{feedbackDto.GetRadar207ByBits(feedbackDto.Wm207)}");
                }


                //209--212
                bool isValid = ValidateConditions(feedbackDto.Wm209, feedbackDto.Wm210, feedbackDto.Wm211, feedbackDto.Wm212);
                if (isValid)
                {
                    Console.WriteLine("所有条件均满足！");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"条件校验失败: {ex.Message}");
                throw Oops.Oh($"Redis读取rgv数据校验出错:{ex.Message}");

            }

            //连接对方的PDA数据库获取货物信息类 分配
            var meteria = new
            {
                id = 2,
                organize_code = "33P1",
                wh_no = "仓库代码",
                erp_order_no = "erp单号",

                order_no = "MOVE202504230945",
                bus_type = 107,
                erp_zone_no = "erp库存地址",

                //物料编码

                part_no = "PT20240424001",
                part_name_rdd = "产品1",
                package_no = "托盘编码",
                sn = "sss",

                qty = 20.75m,
                lot_no = "2025-04-22",//制造批次日期
                date_code = "2025-04-22",//收入日期

                is_sync = 2,
                create_date_time = "2025-04-23 15:45:00",
                modify_date_time = "2025-04-23 15:45:00",
                note_1 = "Another Reserved Note 1",
                note_2 = "Another Reserved Note 2",
                note_3 = "Another Reserved Note 3",
                note_4 = "Another Reserved Note 4"
            };

            //var cnew = new InventoryService(_inventory, _userinfo);
            var inventoryInput = new InventoryManagementDto
            {
                MaterialCode = meteria.part_no, // 物料编码  
                MaterialName = meteria.part_name_rdd, // 物料名称  
                Status = InventoryStatus.正常, // 库存状态  
                Available = (WStatusEnum?)(int)StatusEnum.Enable, // 是否有货  
                BoxCode = "", // 箱条码  ,
                Batch=meteria.lot_no,//批次
            };
            var c1 = JsonConvert.SerializeObject(inventoryInput);
            //查询本地库存 
            var InventoryManagement = await GetInventoryList(inventoryInput);


            var inventoryList = await GetInventoryList(new InventoryManagementDto
            {
                MaterialName = meteria.part_name_rdd,
                MaterialCode = meteria.part_no,
            });
            //按照托盘号分组获取库存库位信息
            InventoryManagement.Where(c => c.Status == InventoryStatus.正常).GroupBy(c => c.Palcode).FirstOrDefault();

            if (inventoryList.Count > 0)
            {
                //判断库位逻辑是否占用，按照类型排序最优

                //将位库置拿出来使用
            }
            //

            //库口  提升机



            //库存表信息
            InventoryManagementEntity managementEntity = new InventoryManagementEntity();

            //if (warehousPositResult != null && warehousPositResult.Result.Items != null)
            //{
            //    var warehousPositList = warehousPositResult.Result.Items.Cast<WarehousePositionEntity>().ToList();
            //    foreach (var warehousePosition in warehousPositList)
            //    {
            //        warehousePosition. = meteria.organize_code;
            //    }
            //}

            //获取库位信息

            //都没问题下发  
            // 指令下发数组示例  
            var rgvCommand = new ushort[16];
            rgvCommand[0] = rgvDto.Wm000; // 控制指令字  
            var rgvdto = new WcsReaderWriteRgv
            {
                Wm000 = rgvDto.Wm000,
                Wm001 = rgvDto.Wm001,
                Wm002 = rgvDto.Wm002,
                Wm003 = rgvDto.Wm003,
                Wm004_Wm005 = rgvDto.Wm004_Wm005,
                Wm006_Wm007 = rgvDto.Wm006_Wm007,
                Wm008 = rgvDto.Wm008,
                Wm014 = rgvDto.Wm014,
                Wm016 = rgvDto.Wm016,
            };
            //发送topic和json信息给mqtt
            var json = JsonConvert.SerializeObject(rgvdto);
            string newtopic = "devices/" + topic + "/telemetry";
            //var c = await _mqttClientService.PublishMessage(newtopic, json);
            //var r= c.Data;
            //return c.IsSuccess;
            return true;
        }
        else
        {
            throw Oops.Oh("AGV正在运行中，请稍后再试");
        }
    }

    /// <summary>  
    /// 校验 Wm205和207 的 n 位  必须全是1
    /// </summary>  
    /// <param name="wm205">Wm205 值</param>  
    /// <param name="s">开始下标</param>  
    /// <param name="e">结束下标</param>  
    /// <returns>是否校验通过</returns>  
    private bool ValidateWm205Bits(ushort wm205, int s, int e)
    {
        // 假设需要校验的 5 位为最低的 5 位  
        for (int i = s; i < e; i++)
        {
            if (((wm205 >> i) & 1) == 0)
            {
                return false;
            }
        }
        return true;
    }
    /// <summary>
    /// 条件判断逻辑 209-212
    /// </summary>
    /// <param name="positionx">X位置值（单位MM）</param>
    /// <param name="positiony">Y位置值（单位MM）</param>
    /// <param name="voltage">电压值（单位0.1V）</param>
    /// <param name="servoPosition">顶升伺服当前位置</param>
    /// <returns>是否满足条件</returns>
    private bool ValidateConditions(int positionx, int positiony, int voltage, int servoPosition)
    {
        // 判断位置值是否超出正负100
        if (positionx < -200 || positionx > 200 || Math.Abs(positionx) > 100)
        {
            throw Oops.Oh("X扫描不到码值，位置值超出范围！");
        }
        if (positiony < -200 || positiony > 200 || Math.Abs(positionx) > 100)
        {
            throw Oops.Oh("Y扫描不到码值，位置值超出范围！");
        }
        // 判断电压值是否有效
        if (voltage == 0 || (voltage / 100.0) <= 0)
        {
            throw Oops.Oh("电压值无效！");
        }

        // 判断顶升伺服当前位置是否在有效范围内
        if (servoPosition < 0 || servoPosition > 9000)
        {
            throw Oops.Oh("顶升伺服当前位置超出范围！");
        }

        // 所有条件均满足
        return true;
    }



    #region 库存查询

    [HttpPost]
    public async Task<List<InventoryManagementEntity>> GetInventoryList(InventoryManagementDto Inventoryinput)
    {

        var list = await _inventory.AsQueryable()
         .WhereIF(!string.IsNullOrWhiteSpace(Inventoryinput.MaterialCode), u => u.MaterialCode == Inventoryinput.MaterialCode)
         .WhereIF(!string.IsNullOrWhiteSpace(Inventoryinput.Batch), u => u.Batch == Inventoryinput.Batch)
        .WhereIF(Enum.IsDefined(typeof(InventoryStatus), Inventoryinput.Status), u => u.Status.Equals(Inventoryinput.Status))
            .OrderBy(u => u.CreateTime, SqlSugar.OrderByType.Desc).ToListAsync();
        return list;
    }
    #endregion
    /// <summary>  
    /// 将泛型List<T>转换为List<object>或提取其数据  
    /// </summary>  
    /// <typeparam name="T">泛型类型</typeparam>  
    /// <param name="genericList">泛型列表</param>  
    /// <returns>转换后的List<object></returns>  
    public List<object> ConvertGenericListToObjectList<T>(List<T> genericList)
    {
        return genericList.Cast<object>().ToList();
    }

    /// <summary>  
    /// 提取泛型List<T>中的数据并进行操作  
    /// </summary>  
    /// <typeparam name="T">泛型类型</typeparam>  
    /// <param name="genericList">泛型列表</param>  
    public void ProcessGenericListData<T>(List<T> genericList)
    {
        foreach (var item in genericList)
        {
            // 在这里对每个item进行操作  
            Console.WriteLine(item.ToString());
        }
    }
}
